package com.xmh.myutil.othertest;

import com.obs.services.ObsClient;
import com.obs.services.ObsConfiguration;
import com.obs.services.exception.ObsException;
import com.obs.services.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

@Slf4j
@Component
@PropertySource(value = "classpath:HuaWeiCloudFile.properties")
public class HuaWeiCloudFileUtil {

    private static String ak;

    private static String sk;

    private static String hotBucketName;

    private static String lowBucketName;

    private static String bakBucketName;

    private static String endPoint;

    private static String dowloadFilePath;

    private static ObsClient obsClient;

    private static Boolean isInit = true;

    /**
     * 打开链接捅
     */
    private static ObsClient openConnection() {
        ObsConfiguration config = new ObsConfiguration();
        config.setSocketTimeout(30000);
        config.setConnectionTimeout(10000);
        config.setEndPoint(endPoint);
        return new ObsClient(ak, sk, config);
    }

    /**
     * 打开链接捅，一次性，不关闭
     */
    private static void openConnectionAndDontClose() {
        if (isInit) {
            synchronized (isInit) {
                if (!isInit) {
                    return;
                }
            }
        } else {
            return;
        }
        ObsConfiguration config = new ObsConfiguration();
        config.setSocketTimeout(30000);
        config.setConnectionTimeout(10000);
        config.setEndPoint(endPoint);
        obsClient = new ObsClient(ak, sk, config);
    }

    /**
     * 关闭链接捅
     */
    private static void closeConnection(ObsClient obsClient) {
        if (obsClient != null) {
            try {
                obsClient.close();
            } catch (IOException e) {
                log.error("", e);
            }
        }
    }

    /**
     * 将is流上传到华为云
     *
     * @param bucketName
     * @param objectKey
     * @param input
     * @throws FileNotFoundException
     * @throws IOException
     */
    public static void uploadFile(String bucketName, String objectKey, InputStream input)
            throws FileNotFoundException, IOException {
        ObsClient openConnection = openConnection();
        try {
            InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest();
            request.setBucketName(bucketName);
            request.setObjectKey(objectKey);
            InitiateMultipartUploadResult result = openConnection.initiateMultipartUpload(request);

            UploadPartResult uploadPartResult = openConnection.uploadPart(bucketName, objectKey, result.getUploadId(),
                    1, input);

            CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest();
            completeMultipartUploadRequest.setBucketName(bucketName);
            completeMultipartUploadRequest.setObjectKey(objectKey);
            completeMultipartUploadRequest.setUploadId(result.getUploadId());

            PartEtag partEtag = new PartEtag();
            partEtag.setPartNumber(uploadPartResult.getPartNumber());
            partEtag.seteTag(uploadPartResult.getEtag());
            completeMultipartUploadRequest.getPartEtag().add(partEtag);

            openConnection.completeMultipartUpload(completeMultipartUploadRequest);
        } catch (ObsException e) {
            System.out.println("Response Code: " + e.getResponseCode());
            System.out.println("Error Message: " + e.getErrorMessage());
            System.out.println("Error Code:       " + e.getErrorCode());
            System.out.println("Request ID:      " + e.getErrorRequestId());
            System.out.println("Host ID:           " + e.getErrorHostId());
        } finally {
            closeConnection(openConnection);
        }
    }

    /**
     * 获取文件的InputStream流
     *
     * @param bucketName
     * @param fileKey
     * @return
     */
    public static InputStream getFileInputStream(String bucketName, String fileKey) {
        ObsClient openConnection = openConnection();
        try {
            ObsObject obsObject = openConnection.getObject(bucketName, fileKey, null);

            return obsObject.getObjectContent();
        } finally {
            closeConnection(openConnection);
        }
    }

    /**
     * 获取文件的byte流数组
     *
     * @param bucketName
     * @param fileKey
     * @return
     */
    public static byte[] getFileBytes(String bucketName, String fileKey) {
        ObsClient openConnection = openConnection();
        try {
            ObsObject obsObject = openConnection.getObject(bucketName, fileKey, null);

            return toByteArray(obsObject.getObjectContent());
        } catch (IOException e) {
            log.error("", e);
        } finally {
            closeConnection(openConnection);
        }
        return null;
    }

    /**
     * 下载文件到配置的服务器路径
     *
     * @param bucketName
     * @param fileKey
     */
    public static void downloadFile(String bucketName, String fileKey) {
        ObsClient openConnection = openConnection();
        try {
            File localFile = new File(dowloadFilePath + fileKey);
            if (!localFile.getParentFile().exists()) {
                localFile.getParentFile().mkdirs();
            }
            downloadToLocalFile(openConnection, bucketName, fileKey);
        } catch (ObsException e) {
            log.error("Response Code: " + e.getResponseCode());
            log.error("Error Message: " + e.getErrorMessage());
            log.error("Error Code:       " + e.getErrorCode());
            log.error("Request ID:      " + e.getErrorRequestId());
            log.error("Host ID:           " + e.getErrorHostId());
        } catch (IOException e) {
            log.error("", e);
        } finally {
            closeConnection(openConnection);
        }
    }

    /**
     * 下载文件到指定文件夹
     *
     * @param bucketName
     * @param objectKey
     * @throws ObsException
     * @throws IOException
     */
    private static void downloadToLocalFile(ObsClient obsClient, String bucketName, String objectKey)
            throws ObsException, IOException {
        ObsObject obsObject = obsClient.getObject(bucketName, objectKey, null);
        ReadableByteChannel rchannel = Channels.newChannel(obsObject.getObjectContent());

        ByteBuffer buffer = ByteBuffer.allocate(4096);
        WritableByteChannel wchannel = Channels.newChannel(new FileOutputStream(new File(dowloadFilePath + objectKey)));

        while (rchannel.read(buffer) != -1) {
            buffer.flip();
            wchannel.write(buffer);
            buffer.clear();
        }
        rchannel.close();
        wchannel.close();
    }

    /**
     * is流转换为byte数组
     *
     * @param input
     * @return
     * @throws IOException
     */
    public static byte[] toByteArray(InputStream input) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[4096];
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
        }
        return output.toByteArray();
    }

    @Value("${accessKey}")
    public void setAk(String ak) {
        HuaWeiCloudFileUtil.ak = ak;
    }

    @Value("${securityKey}")
    public void setSk(String sk) {
        HuaWeiCloudFileUtil.sk = sk;
    }

    @Value("${bucketName_hot}")
    public void setHotBucketName(String hotBucketName) {
        HuaWeiCloudFileUtil.hotBucketName = hotBucketName;
    }

    @Value("${bucketName_low}")
    public void setLowBucketName(String lowBucketName) {
        HuaWeiCloudFileUtil.lowBucketName = lowBucketName;
    }

    @Value("${bucketName_bak}")
    public void setBakBucketName(String bakBucketName) {
        HuaWeiCloudFileUtil.bakBucketName = bakBucketName;
    }

    @Value("${endPoint}")
    public void setEndPoint(String endPoint) {
        HuaWeiCloudFileUtil.endPoint = endPoint;
    }

    @Value("${dowload_file_path}")
    public void setDowloadFilePath(String dowloadFilePath) {
        HuaWeiCloudFileUtil.dowloadFilePath = dowloadFilePath;
    }

    public static String getHotBucketName() {
        return hotBucketName;
    }

    public static String getLowBucketName() {
        return lowBucketName;
    }

    public static String getBakBucketName() {
        return bakBucketName;
    }
}
